package com.koron.operation.classes.shift.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.koron.bean.query.OrderItem;
import com.koron.bean.query.PageQuery;
import com.koron.operation.classes.schedule.bean.dto.ClassesShiftDTO;
import com.koron.operation.classes.schedule.bean.po.ClassesSchedule;
import com.koron.operation.classes.schedule.service.ClassesScheduleService;
import com.koron.operation.classes.schedule.service.ClassesShiftService;
import com.koron.operation.classes.shift.bean.dto.ShiftRecordDTO;
import com.koron.operation.classes.shift.bean.po.ClassesShiftRecord;
import com.koron.operation.classes.shift.bean.po.ClassesTip;
import com.koron.operation.classes.shift.bean.po.ClassesWorkCompletion;
import com.koron.operation.classes.shift.bean.query.ShiftQuery;
import com.koron.operation.classes.shift.bean.query.ShiftRecordQuery;
import com.koron.operation.classes.shift.bean.vo.ShiftRecordVO;
import com.koron.operation.classes.shift.mapper.ClassesShiftRecordMapper;
import com.koron.operation.classes.shift.service.ClassesShiftRecordService;
import com.koron.operation.classes.shift.service.ClassesTipService;
import com.koron.operation.classes.shift.service.ClassesWorkCompletionService;
import org.apache.commons.collections4.CollectionUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 交接班记录(ClassesShiftRecord)表服务实现类
 *
 * @author jzp
 * @since 2021-10-27 18:36:22
 */
@Service
public class ClassesShiftRecordServiceImpl implements ClassesShiftRecordService {

    @Autowired
    private ClassesTipService classesTipService;

    @Autowired
    private ClassesWorkCompletionService workCompletionService;

    @Autowired
    private ClassesScheduleService classesScheduleService;

    @Autowired
    private ClassesShiftService classesShiftService;

    /**
     * 通过ID查询单条数据
     * 不查询工作完成情况和交接事项
     */
    @Override
    @TaskAnnotation("getById")
    public ClassesShiftRecord getById(SessionFactory factory, String id) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        return mapper.selectById(id);
    }

    @Override
    @TaskAnnotation("getVoById")
    public ShiftRecordVO getVoById(SessionFactory factory, String id) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        return mapper.selectVoById(id);
    }

    @Override
    @TaskAnnotation("getOne")
    public ClassesShiftRecord getOne(SessionFactory factory, ShiftQuery shiftQuery) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        return mapper.selectOne(shiftQuery);
    }

    @Override
    @TaskAnnotation("getDTOOne")
    public ShiftRecordDTO getDTOOne(SessionFactory factory, ShiftQuery shiftQuery) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        List<ShiftRecordDTO> shiftRecordDTOList = mapper.selectByCondition(shiftQuery);

        // 如果为空或大小为0，直接返回null
        if (CollectionUtils.isEmpty(shiftRecordDTOList)) {
            return null;
        }
        // 如果大小为1，拿第一个
        if (shiftRecordDTOList.size() == 1) {
            return shiftRecordDTOList.get(0);
        }

        // 如果有多个，按不为null计算优先级：nextShiftId，thisTime，nextTime
        return shiftRecordDTOList.stream().min(Comparator.<ClassesShiftRecord>comparingInt(e -> e.sortNum(ClassesShiftRecord::getNextShiftId))
                        .thenComparing(e -> e.sortNum(ClassesShiftRecord::getThisTime))
                        .thenComparing(e -> e.sortNum(ClassesShiftRecord::getNextTime)))
                .orElse(null);
    }

    /**
     * 查询交接班记录数据
     * 本值状态：空（首班）、1值班中、2已交班
     * 下值状态：空（末班）、0未接班
     */
    @Override
    @TaskAnnotation("getByCondition")
    public ShiftRecordDTO getByCondition(SessionFactory factory, ShiftQuery shiftQuery) {
        ShiftRecordDTO shiftRecordDTO = getDTOOne(factory, shiftQuery);
        // 如果没有交接班记录，则手动查，并保存
        if (shiftRecordDTO == null) {
            ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
            shiftRecordDTO = new ShiftRecordDTO();

            // 查询本值班次信息
            String thisShiftId = shiftQuery.getThisShiftId();
            Assert.hasText(thisShiftId, "本值id不能为空");
            ClassesShiftDTO thisShiftDTO = mapper.selectShiftDtoById(thisShiftId);
            // 设置本值班次信息
            shiftRecordDTO.setThisShiftId(thisShiftDTO.getId());
            shiftRecordDTO.setThisShift(thisShiftDTO);

            // 查询下值班次信息
            String nextShiftId = shiftQuery.getNextShiftId();
            if (!StringUtils.isEmpty(nextShiftId)) {
                ClassesShiftDTO nextShiftDTO = mapper.selectShiftDtoById(nextShiftId);
                // 设置下值班次信息
                shiftRecordDTO.setNextShiftId(nextShiftDTO.getId());
                shiftRecordDTO.setNextShift(nextShiftDTO);
            }

            // 查询排班方案信息
            ClassesSchedule classesSchedule = classesScheduleService.getById(factory, thisShiftDTO.getScheduleId());
            // 设置排班方案信息
            shiftRecordDTO.setScheduleId(classesSchedule.getId());
            shiftRecordDTO.setScheduleName(classesSchedule.getName());
            shiftRecordDTO.setStaffType(classesSchedule.getStaffType());
            shiftRecordDTO.setDeptId(classesSchedule.getDeptId());
            shiftRecordDTO.setDeptName(classesSchedule.getDeptName());
            shiftRecordDTO.setLocationId(classesSchedule.getLocationId());
            shiftRecordDTO.setLocationName(classesSchedule.getLocationName());

            save(factory, shiftRecordDTO);
        }
        Assert.state(shiftRecordDTO.getThisShift().getStatus() != 0, "本值不可能为未接班");

        // 如果数据库没有保存交接事项，则查询上一个交接班的交接事项，并保存
        if (CollectionUtils.isEmpty(shiftRecordDTO.getTips())) {
            List<ClassesTip> tips = classesTipService.getByCondition(factory, shiftRecordDTO.getThisShiftId(), shiftRecordDTO.extractWorkFeignQuery());
            if (!CollectionUtils.isEmpty(tips)) {
                classesTipService.removeByRecordId(factory, shiftRecordDTO.getId());
                String recordDTOId = shiftRecordDTO.getId();
                tips.forEach(e -> {
                    e.setRecordId(recordDTOId);
                    e.setId(null);
                });
                classesTipService.saveBatch(factory, tips);
                shiftRecordDTO.setTips(tips.stream().filter(ClassesTip::noDisplayFlag).collect(Collectors.toList()));
            }
        }
        if (!CollectionUtils.isEmpty(shiftRecordDTO.getTips())) {
            shiftRecordDTO.getTips().sort(Comparator.comparing(ClassesTip::noNullSort));
        }
        // 如果数据库没有保存工作完成情况，则手动查询
        if (CollectionUtils.isEmpty(shiftRecordDTO.getWorkCompletions())) {
            shiftRecordDTO.setWorkCompletions(workCompletionService.getFeignByCondition(shiftRecordDTO.extractWorkFeignQuery()));
        }

        return shiftRecordDTO;
    }

    @Override
    @TaskAnnotation("list")
    public List<ShiftRecordDTO> list(SessionFactory factory, ShiftRecordQuery query) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        return mapper.selectList(query);
    }

    /**
     * 查询所有数据
     */
    @Override
    @TaskAnnotation("listVo")
    public List<ShiftRecordVO> listVo(SessionFactory factory, ShiftRecordQuery query) {
        List<ShiftRecordDTO> shiftRecordDTOList = list(factory, query);
        return listDtoToVo(factory, shiftRecordDTOList);
    }

    private List<ShiftRecordVO> listDtoToVo(SessionFactory factory, List<ShiftRecordDTO> shiftRecordDTOList) {
        List<ShiftRecordVO> shiftRecordVOList = new ArrayList<>();
        for (ShiftRecordDTO shiftRecordDTO : shiftRecordDTOList) {
            ShiftRecordVO shiftRecordVO = BeanUtil.toBean(shiftRecordDTO, ShiftRecordVO.class);
            // 设置本值时间
            ClassesShiftDTO thisShift = shiftRecordDTO.getThisShift();
            if (thisShift == null) {
                thisShift = classesShiftService.getDtoById(factory, shiftRecordDTO.getThisShiftId());
            }
            if (thisShift != null) {
                thisShift = classesShiftService.getDtoById(factory, shiftRecordDTO.getThisShiftId());
                shiftRecordVO.setThisName(thisShift.getName());
                shiftRecordVO.setThisStartTime(thisShift.getStartTime());
                shiftRecordVO.setThisEndTime(thisShift.getEndTime());
                shiftRecordVO.setThisStaffs(thisShift.getStaffs());
            }

            // 设置本值时间
            ClassesShiftDTO nextShift = shiftRecordDTO.getNextShift();
            if (nextShift == null) {
                nextShift = classesShiftService.getDtoById(factory, shiftRecordDTO.getNextShiftId());
            }
            if (nextShift != null) {
                shiftRecordVO.setNextName(nextShift.getName());
                shiftRecordVO.setNextStartTime(nextShift.getStartTime());
                shiftRecordVO.setNextEndTime(nextShift.getEndTime());
                shiftRecordVO.setNextStaffs(nextShift.getStaffs());
            }
            shiftRecordVOList.add(shiftRecordVO);
        }
        return shiftRecordVOList;
    }

    @Override
    @TaskAnnotation("page")
    public PageInfo<ShiftRecordVO> page(SessionFactory factory, PageQuery pageQuery, ShiftRecordQuery query) {
        if (CollectionUtils.isEmpty(pageQuery.getOrders())) {
            pageQuery.setOrders(Collections.singletonList(new OrderItem("createTime", false)));
        }
        pageQuery.getOrders().forEach(e -> e.setPrefix("classesShiftRecord"));
        PageHelper.startPage(pageQuery.getPage(), pageQuery.getPageSize(), pageQuery.getOrderBy());
        List<ShiftRecordDTO> list = list(factory, query);
        PageInfo<ShiftRecordDTO> pageInfo = new PageInfo<>(list);
        PageHelper.clearPage();
        List<ShiftRecordVO> shiftRecordVOList = listDtoToVo(factory, list);
        PageInfo<ShiftRecordVO> shiftRecordVOPageInfo = new PageInfo<>(shiftRecordVOList);
        shiftRecordVOPageInfo.setTotal(pageInfo.getTotal());
        return shiftRecordVOPageInfo;
    }

    /**
     * 新增数据
     */
    @Override
    @TaskAnnotation("save")
    public boolean save(SessionFactory factory, ClassesShiftRecord classesShiftRecord) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        return mapper.insertOrUpdate(classesShiftRecord) > 0;
    }

    @Override
    @TaskAnnotation("saveBatch")
    public boolean saveBatch(SessionFactory factory, List<ClassesShiftRecord> classesShiftRecords) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        return mapper.insertOrUpdateBatch(classesShiftRecords) > 0;
    }

    @Override
    @TaskAnnotation("saveOrUpdateDto")
    public boolean saveOrUpdateDto(SessionFactory factory, ShiftRecordDTO shiftRecordDTO) {
        // 1. 保存基本数据
        save(factory, shiftRecordDTO);

        // 2. 保存配置信息
        List<ClassesTip> tips = shiftRecordDTO.getTips();
        if (tips != null) {
            classesTipService.removeByRecordId(factory, shiftRecordDTO.getId());
            tips.forEach(e -> e.setRecordId(shiftRecordDTO.getId()));
            classesTipService.saveBatch(factory, tips);
        }

        // 3. 保存工作完成情况信息
        List<ClassesWorkCompletion> workCompletions = shiftRecordDTO.getWorkCompletions();
        if (workCompletions != null) {
            workCompletionService.removeByRecordId(factory, shiftRecordDTO.getId());
            workCompletions.forEach(e -> e.setRecordId(shiftRecordDTO.getId()));
            workCompletionService.saveBatch(factory, workCompletions);
        }

        return true;
    }

    /**
     * 修改数据
     */
    @Override
    @TaskAnnotation("update")
    public boolean update(SessionFactory factory, ClassesShiftRecord classesShiftRecord) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        return mapper.update(classesShiftRecord) > 0;
    }

    /**
     * 通过主键删除数据
     */
    @Override
    @TaskAnnotation("deleteById")
    public boolean deleteById(SessionFactory factory, String id) {
        ClassesShiftRecordMapper mapper = factory.getMapper(ClassesShiftRecordMapper.class);
        return mapper.hidden(id) > 0;
    }
}
